import { isFunction } from "@/utils/is"
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"
import Axios from "axios"
import { cloneDeep } from "lodash-es"
import { AxiosCanceler } from "./axiosCancel"
import { RequestOptions, Result } from "./types"

class VueAxios {
  private axiosInstance: AxiosInstance
  private readonly opts: any

  constructor(options: any) {
    this.opts = options
    this.axiosInstance = Axios.create(options)
    this.setTnterceptorsService()
  }

  /**
   * 获取axios实例对象
   */
  getAxios(): AxiosInstance {
    return this.axiosInstance
  }

  private getTransform() {
    const { transform } = this.opts
    return transform
  }

  /**
   *  设置拦截器
   */
  setTnterceptorsService() {
    const transform = this.getTransform()
    if (!transform) {
      return
    }

    const {
      requestInterceptors,
      requestInterceptorsCatch,
      responseInterceptors,
      responseInterceptorsCatch
    } = transform

    const axiosCanceler = new AxiosCanceler()

    // 请求拦截器配置处理
    this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
      const { headers: { ignoreCancelToken } = { ignoreCancelToken: false } } = config
      !ignoreCancelToken && axiosCanceler.addPending(config)
      if (requestInterceptors && isFunction(requestInterceptors)) {
        config = requestInterceptors(config)
      }
      return config
    }, undefined)

    // 请求拦截器错误捕获
    requestInterceptorsCatch &&
      isFunction(requestInterceptorsCatch) &&
      this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch)

    // 响应结果拦截器处理
    this.axiosInstance.interceptors.response.use((res: AxiosResponse<any>) => {
      res && axiosCanceler.removePending(res.config)
      if (responseInterceptors && isFunction(responseInterceptors)) {
        res = responseInterceptors(res)
      }
      return res
    }, undefined)

    // 响应结果拦截器错误捕获
    responseInterceptorsCatch &&
      isFunction(responseInterceptorsCatch) &&
      this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch)
  }
  /**
   * @description 所有请求封装成一个方法
   * @param url 请求地址
   * @param method 请求方法
   * @param data 请求参数体
   */
  request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
    const conf = cloneDeep(config)
    const transform = this.getTransform()

    const { transformRequestData } = transform
    const { requestOptions } = this.opts
    const opt: RequestOptions = Object.assign({}, requestOptions, options)

    return new Promise((resolve, reject) => {
      this.axiosInstance
        .request<any, AxiosResponse<Result>>(conf)
        .then((res: AxiosResponse<Result>) => {
          console.log("res: AxiosResponse<Result>", res)
          if (transformRequestData && isFunction(transformRequestData)) {
            const t = transformRequestData(res, opt)
            resolve(t)
            return
          }
          resolve((res as unknown) as Promise<T>)
        })
        .catch((err: Error) => {
          // todos 补充异常处理
          reject(err)
        })
    })
  }

  /**
   * GET 简单的get请求
   * @param url
   * @returns {*} 返回结果
   */

  // get<T>(url: string): AxiosResponse<T> {

  // }
}

export default VueAxios
